package com.easy.mongodb.core.biz;

import cn.hutool.json.JSONUtil;
import com.mongodb.client.model.IndexModel;
import lombok.Data;
import lombok.experimental.Accessors;
import org.bson.codecs.configuration.CodecProvider;

import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * @ProjectName: easy-mongodb
 * @Description: 实体类信息
 * @Author: vapeshop
 * @Date: 2022/6/20 10:04:13
 * @UpdateUser: vapeshop
 * @UpdateDate: 2022/6/20 10:04:13
 * @UpdateRemark: The modified content
 * @Version: 1.0
 * <p>
 * Copyright © 2022 vapeshop Technologies Inc. All Rights Reserved
 **/
@Data
@Accessors(chain = true)
public class TableInfo {
    /**
     * mongo索引参数
     */
    private final Map<String, IndexModel> indexOps = new HashMap<>();
    /**
     * 实体字段-mongo实际字段映射
     */
    private final Map<String, String> mappingColumnMap = new HashMap<>();
    /**
     * mongo实际字段映射->实体字段 (仅包含被重命名字段)
     */
    private final Map<String, String> columnMappingMap = new HashMap<>();
    /**
     * 嵌套类型 path和class对应关系
     */
    private final Map<String, Class<?>> pathClassMap = new HashMap<>();
    /**
     * 嵌套类型 实体字段->mongo实际字段映射
     */
    private final Map<Class<?>, Map<String, String>> nestedClassMappingColumnMap = new HashMap<>();
    /**
     * 嵌套类型 mongo实际字段映射->实体字段 (仅包含被重命名字段)
     */
    private final Map<Class<?>, Map<String, String>> nestedClassColumnMappingMap = new HashMap<>();
    /**
     * id数据类型 如Long.class String.class
     */
    private Class<?> idClass;
    /**
     * 数据名(mongo中数据库名称)
     */
    private String database;
    /**
     * 表名(mongo中集合名称)
     */
    private String collectionName;
    /**
     * 表映射结果集
     */
    private String resultMap;
    /**
     * 主键字段
     */
    private Field keyField;
    /**
     * 表主键ID 属性名
     */
    private String keyProperty;
    /**
     * 嵌套类的字段信息列表
     */
    private Map<Class<?>, List<TableFieldInfo>> nestedFieldListMap = new HashMap<>();
    /**
     * 表字段信息列表
     */
    private List<TableFieldInfo> fieldList;
    /**
     * 标记id字段属于哪个类
     */
    private Class<?> clazz;
    /**
     * 转换器
     */
    private CodecProvider pojoCodecProvider;

    /**
     * 获取需要进行查询的字段列表
     *
     * @param predicate 预言
     * @return 查询字段列表
     */
    public List<String> chooseSelect(Predicate<TableFieldInfo> predicate) {
        return this.fieldList.stream()
                .filter(predicate)
                .map(TableFieldInfo::getColumn)
                .collect(Collectors.toList());
    }

    /**
     * 获取实体字段映射mongo中的字段名
     *
     * @param column 字段名
     * @return mongo中的字段名
     */
    public String getMappingColumn(String column) {
        return Optional.ofNullable(this.mappingColumnMap.get(column))
                .orElse(column);
    }

    /**
     * 获取全部嵌套类
     *
     * @return 嵌套类集合
     */
    public Set<Class<?>> getAllNestedClass() {
        return this.nestedClassColumnMappingMap.keySet();
    }

    /**
     * 根据path获取嵌套类字段关系map
     *
     * @param path 路径
     * @return 字段关系map
     */
    public Map<String, String> getNestedMappingColumnMapByPath(String path) {
        return Optional.ofNullable(this.pathClassMap.get(path))
                .map(this.nestedClassMappingColumnMap::get)
                .orElse(new HashMap<>(0));
    }

    @Override
    public String toString() {
        return JSONUtil.toJsonPrettyStr(this);
    }
}
